#include "Processor.h"
#include "jsmin.h"
#include "I18n.h"
#include "Command.h"
#include <sstream>

#define DEFAULT_CMD_NAME "render"
#define PARAM_LOCALE "l"

namespace phnq
{
	namespace phnqlets
	{
		static phnq::kit::log::Logger *log = phnq::kit::log::Logger::get("phnq::phnqlets::Processor");
		
		Processor::Processor()
		{
		}

		Processor::~Processor()
		{
			if(response.bodyStream)
				delete response.bodyStream;
		}
		
		processor_response* Processor::process(string path, map<string,string> params)
		{
			phnq::kit::log::LoggerTime logTime = log->time();
			
			compression_info compression = Environment::getInstance()->getCompressionForPath(path);
			
			// setup the default response values
			response.status = STATUS_OK;
			response.clientCacheDuration = 0;
			response.deflate = (compression.type == COMPRESSION_DEFLATE_STATIC || compression.type == COMPRESSION_DEFLATE_DYNAMIC);
			response.bodyStream = NULL;
			
			if(compression.type == COMPRESSION_DEFLATE_STATIC)
			{
				// return the cached and compressed response here, or if it has
				// not been generated and cached yet let it happen and then
				// cache it below.
			}

			// set the locale for the thread
			string locale = params[PARAM_LOCALE];
			if(locale != "")
				I18n::setCurrentLocale(locale);
			
			// extract the command name and the relative path from the path
			size_t slashIdx = path.find_first_of("/");
			size_t relPathIdx = slashIdx == string::npos ? 0 : slashIdx+1;
			string cmdName = slashIdx == string::npos ? DEFAULT_CMD_NAME : path.substr(0, slashIdx);
			string relPath = path.substr(relPathIdx);
			
			// enable jsmin for thread
			set_jsmin_enabled_for_thread(true);
			
			// create the command from the factory, execute it and dispose of it
			Command *cmd = Command::create(cmdName);
			cmd->execute(relPath, params, &response);
			Command::dispose(cmd);
			
			// if the command yielded a "not found", then try again with the static file command
			if(response.status == STATUS_NOT_FOUND)
			{
				if(response.bodyStream)
					delete response.bodyStream;
				
				response.status = STATUS_OK;
				Command *staticFileCmd = Command::createStaticFileCommand();
				staticFileCmd->execute(path, params, &response);
				Command::dispose(staticFileCmd);
			}
			
			// unset the jsmin for the thread
			unset_jsmin_enabled_for_thread();

			// set the body stream if not set
			if(response.bodyStream == NULL)
				response.bodyStream = new istringstream("");
			
			// compress if needed
			if(compression.type == COMPRESSION_DEFLATE_DYNAMIC || compression.type == COMPRESSION_DEFLATE_STATIC)
			{
				istream *bodyStream = response.bodyStream;
				response.bodyStream = new boost::iostreams::stream<DeflatorSource>(bodyStream, compression.level);
				
				if(compression.type == COMPRESSION_DEFLATE_STATIC)
				{
					// cache the response here...
				}
			}
			
			// log the processing event with ellapsed time
			log->debug(logTime, "processed: %s", path.c_str());
			
			return &response;
		}
	}
}
